package com.csw.shuanfa.bitset;


import java.util.ArrayList;
import java.util.Comparator;
import java.util.DoubleSummaryStatistics;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * https://mp.weixin.qq.com/s/Sq4hKTxnBpSMjPQrIHRbmg
 * +--------------------+       +------+   +------+   +---+   +-------+
 * | stream of elements +-----> |filter+-> |sorted+-> |map+-> |collect|
 * +--------------------+       +------+   +------+   +---+   +-------+
 */
public class StreamUserPOTest {
    public static void main(String[] args) {
        List<UserPO> list = new ArrayList();
        list.add(new UserPO("张三1", 11.0));
        list.add(new UserPO("李四2", 33.0));
        list.add(new UserPO("王五3", 22.0));
        list.add(new UserPO("赵六4", null));

        /**
         * filter：过滤，就是过滤器，符合条件的通过，不符合条件的过滤掉
         */

        //统计出分数不为空的人
        int count = (int) list.stream().filter(u -> u.getScore() != null).count();
        //统计出分数不为空的人】" + count);

        /**
         * map：映射，他将原集合映射成为新的集合，在VO、PO处理的过程中较常见。在本例子中，原集合就是PO集合，
         * 新集合可以自定义映射为成绩集合，同时也可以对新集合进行相关操作
         */
        //取出所有学生的成绩
        List<Double> scoreList = list.stream().map(p -> p.getScore()).collect(Collectors.toList());
        //取出所有学生的成绩】" + scoreList);

        //将学生姓名合成字符串用逗号分隔
        String nameString = list.stream().map(p -> p.getName()).collect(Collectors.joining(","));
        //将学生姓名合成字符串用逗号分隔】" + nameString);

        /**
         * sorted：排序，可以根据指定的字段进行排序
         */
        //按学生成绩逆序排序，正序则不需要添加reversed
        List<UserPO> collect = list.stream().filter(p -> p.getScore() != null).sorted(Comparator.comparing(UserPO::getScore).reversed()).collect(Collectors.toList());
        //按学生成绩逆序排序，正序则不需要添加reversed】" + collect);

        /**
         * forEach：这个应该是最常用的，也就是为每一个元素进行自定义操作
         */
        //给每个学生分数+10分
        list.stream().filter(p->p.getScore()!=null).forEach(p -> p.setScore(p.getScore() + 10));
        //改变之后的集合】" + list.toString());

        /**
         * collect：聚合，可以用于GroudBy按指定字段分类，也可以用于返回列表或者拼凑字符串
         */
        //将学生按照成绩分类
        Map<Double, List<UserPO>> doubleListMap = list.stream().filter(p -> p.getScore() != null).collect(Collectors.groupingBy(UserPO::getScore));
        for (Double d : doubleListMap.keySet()) {
            //d + "分数的有" + doubleListMap.get(d).size());
        }
        //取出所有学生的成绩
        List<Double> scoreList2 = list.stream().map(p -> p.getScore()).collect(Collectors.toList());
        //取出所有学生的成绩】" + scoreList2);

        //将学生姓名合成字符串用逗号分隔
        String nameString2 = list.stream().map(p -> p.getName()).collect(Collectors.joining(","));
        //将学生姓名合成字符串用逗号分隔】" + nameString2);

        /**
         * statistics：统计，可以统计中位数，平均值，最大最小值
         */
        DoubleSummaryStatistics statistics = list.stream().filter(p -> p.getScore() != null).mapToDouble(p -> p.getScore()).summaryStatistics();
        //列表中的最大数】" + statistics.getMax());
        //列表中的最小数】" + statistics.getMin());
        //列表中的平均数】" + statistics.getAverage());
        //列表中的所有数】" + statistics.getSum());

        /**
         * parallelStream：并行流，可以利用多线程进行流的操作，提升效率。但是其不具备线程传播性，因此使用时需要充分评估是否需要用并行流操作
         */
        int count2 = (int) list.parallelStream().map(p -> p.getScore() != null).count();
        //并行流统计】" + count2);
    }

}
